#include "gdkx11screen.h"
#include "gdkx11window.h"
#include "gdkx11visual.h"
+#include "gdkvisualprivate.h"
#include "gdkinternals.h"
}
gboolean
-gdk_x11_display_init_gl (GdkDisplay *display)
+gdk_x11_screen_init_gl (GdkScreen *screen)
{
+ GdkDisplay *display = gdk_screen_get_display (screen);
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
- GdkScreen *screen;
Display *dpy;
int error_base, event_base;
int screen_num;
if (!glXQueryExtension (dpy, &error_base, &event_base))
return FALSE;
- screen = gdk_display_get_default_screen (display);
screen_num = GDK_X11_SCREEN (screen)->screen_num;
display_x11->have_glx = TRUE;
epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_buffer_age");
display_x11->has_glx_sync_control =
epoxy_has_glx_extension (dpy, screen_num, "GLX_OML_sync_control");
+ display_x11->has_glx_multisample =
+ epoxy_has_glx_extension (dpy, screen_num, "GLX_ARB_multisample");
+ display_x11->has_glx_visual_rating =
+ epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_visual_rating");
GDK_NOTE (OPENGL,
g_print ("GLX version %d.%d found\n"
True);
}
+struct glvisualinfo {
+ int supports_gl;
+ int double_buffer;
+ int stereo;
+ int alpha_size;
+ int depth_size;
+ int stencil_size;
+ int num_multisample;
+ int visual_caveat;
+};
+
+static gboolean
+visual_compatible (const GdkVisual *a, const GdkVisual *b)
+{
+ return a->type == b->type &&
+ a->depth == b->depth &&
+ a->red_mask == b->red_mask &&
+ a->green_mask == b->green_mask &&
+ a->blue_mask == b->blue_mask &&
+ a->colormap_size == b->colormap_size &&
+ a->bits_per_rgb == b->bits_per_rgb;
+}
+
+static gboolean
+visual_is_rgba (const GdkVisual *visual)
+{
+ return
+ visual->depth == 32 &&
+ visual->red_mask == 0xff0000 &&
+ visual->green_mask == 0x00ff00 &&
+ visual->blue_mask == 0x0000ff;
+}
+
+/* This picks a compatible (as in has the same X visual details) visual
+ that has "better" characteristics on the GL side */
+static GdkVisual *
+pick_better_visual_for_gl (GdkX11Screen *x11_screen,
+ struct glvisualinfo *gl_info,
+ GdkVisual *compatible)
+{
+ GdkVisual *visual;
+ int i;
+ gboolean want_alpha = visual_is_rgba (compatible);
+
+ /* First look for "perfect match", i.e:
+ * supports gl
+ * double buffer
+ * alpha iff visual is an rgba visual
+ * no unnecessary stuff
+ */
+ for (i = 0; i < x11_screen->nvisuals; i++)
+ {
+ visual = x11_screen->visuals[i];
+ if (visual_compatible (visual, compatible) &&
+ gl_info[i].supports_gl &&
+ gl_info[i].double_buffer &&
+ !gl_info[i].stereo &&
+ (want_alpha ? (gl_info[i].alpha_size > 0) : (gl_info[i].alpha_size == 0)) &&
+ (gl_info[i].depth_size == 0) &&
+ (gl_info[i].stencil_size == 0) &&
+ (gl_info[i].num_multisample == 0) &&
+ (gl_info[i].visual_caveat == GLX_NONE_EXT))
+ return visual;
+ }
+
+ if (!want_alpha)
+ {
+ /* Next, allow alpha even if we don't want it: */
+ for (i = 0; i < x11_screen->nvisuals; i++)
+ {
+ visual = x11_screen->visuals[i];
+ if (visual_compatible (visual, compatible) &&
+ gl_info[i].supports_gl &&
+ gl_info[i].double_buffer &&
+ !gl_info[i].stereo &&
+ (gl_info[i].depth_size == 0) &&
+ (gl_info[i].stencil_size == 0) &&
+ (gl_info[i].num_multisample == 0) &&
+ (gl_info[i].visual_caveat == GLX_NONE_EXT))
+ return visual;
+ }
+ }
+
+ /* Next, allow depth and stencil buffers: */
+ for (i = 0; i < x11_screen->nvisuals; i++)
+ {
+ visual = x11_screen->visuals[i];
+ if (visual_compatible (visual, compatible) &&
+ gl_info[i].supports_gl &&
+ gl_info[i].double_buffer &&
+ !gl_info[i].stereo &&
+ (gl_info[i].num_multisample == 0) &&
+ (gl_info[i].visual_caveat == GLX_NONE_EXT))
+ return visual;
+ }
+
+ /* Next, allow multisample: */
+ for (i = 0; i < x11_screen->nvisuals; i++)
+ {
+ visual = x11_screen->visuals[i];
+ if (visual_compatible (visual, compatible) &&
+ gl_info[i].supports_gl &&
+ gl_info[i].double_buffer &&
+ !gl_info[i].stereo &&
+ (gl_info[i].visual_caveat == GLX_NONE_EXT))
+ return visual;
+ }
+
+ return compatible;
+}
+
+void
+_gdk_x11_screen_update_visuals_for_gl (GdkScreen *screen)
+{
+ GdkX11Screen *x11_screen;
+ GdkDisplay *display;
+ GdkX11Display *display_x11;
+ Display *dpy;
+ struct glvisualinfo *gl_info;
+ int i;
+
+ x11_screen = GDK_X11_SCREEN (screen);
+ display = x11_screen->display;
+ display_x11 = GDK_X11_DISPLAY (display);
+
+ if (!gdk_x11_screen_init_gl (screen))
+ return;
+
+ dpy = gdk_x11_display_get_xdisplay (display);
+
+ gl_info = g_new0 (struct glvisualinfo, x11_screen->nvisuals);
+
+ for (i = 0; i < x11_screen->nvisuals; i++)
+ {
+ XVisualInfo *visual_list;
+ XVisualInfo visual_template;
+ int nxvisuals;
+
+ visual_template.screen = x11_screen->screen_num;
+ visual_template.visualid = gdk_x11_visual_get_xvisual (x11_screen->visuals[i])->visualid;
+ visual_list = XGetVisualInfo (x11_screen->xdisplay, VisualIDMask| VisualScreenMask, &visual_template, &nxvisuals);
+
+ if (visual_list == NULL)
+ continue;
+
+ glXGetConfig (dpy, &visual_list[0], GLX_USE_GL, &gl_info[i].supports_gl);
+ glXGetConfig (dpy, &visual_list[0], GLX_DOUBLEBUFFER, &gl_info[i].double_buffer);
+ glXGetConfig (dpy, &visual_list[0], GLX_STEREO, &gl_info[i].stereo);
+ glXGetConfig (dpy, &visual_list[0], GLX_ALPHA_SIZE, &gl_info[i].alpha_size);
+ glXGetConfig (dpy, &visual_list[0], GLX_DEPTH_SIZE, &gl_info[i].depth_size);
+ glXGetConfig (dpy, &visual_list[0], GLX_STENCIL_SIZE, &gl_info[i].stencil_size);
+
+ if (display_x11->has_glx_multisample)
+ glXGetConfig(dpy, &visual_list[0], GLX_SAMPLE_BUFFERS_ARB, &gl_info[i].num_multisample);
+
+ if (display_x11->has_glx_visual_rating)
+ glXGetConfig(dpy, &visual_list[0], GLX_VISUAL_CAVEAT_EXT, &gl_info[i].visual_caveat);
+ else
+ gl_info[i].visual_caveat = GLX_NONE_EXT;
+
+ XFree (visual_list);
+ }
+
+ x11_screen->system_visual = pick_better_visual_for_gl (x11_screen, gl_info, x11_screen->system_visual);
+ if (x11_screen->rgba_visual)
+ x11_screen->rgba_visual = pick_better_visual_for_gl (x11_screen, gl_info, x11_screen->rgba_visual);
+}
+
+
GdkGLContext *
gdk_x11_window_create_gl_context (GdkWindow *window,
gboolean attached,
display = gdk_window_get_display (window);
- if (!gdk_x11_display_init_gl (display))
+ if (!gdk_x11_screen_init_gl (gdk_window_get_screen (window)))
{
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
if (!GDK_IS_X11_DISPLAY (display))
return FALSE;
- if (!gdk_x11_display_init_gl (display))
+ if (!gdk_x11_screen_init_gl (gdk_display_get_default_screen (display)))
return FALSE;
if (major != NULL)